﻿using System;
using System.Linq;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using Web.Models;
using Web.Models.Helpers;
using Wombat.Data.Model;
using Wombat.Data.Model.Dtos;
using Wombat.Data.Model.Factories;
using Tag = Wombat.Data.Model.Tag;

namespace Web.Controllers
{
    public class TagController : Controller
    {
        //
        // GET: /Tag/

        public ActionResult Index()
        {
            using (var db = new WombatEntities())
            {
                var model =
                    db.Tags
                    .Include("Unit")
                    .Select(
                        t => new TagDto {Id = t.Id, Guid = t.Guid, Name = t.Name, Unit = t.Unit.Name, UnitId = t.Unit.Id})
                        .ToList();
                return View(model);
            }
        }

        public string GetName(long id)
        {
            var tag = GetTagByIdAndUpdateViewBag(id);
            return tag.Name;
        }

        [HttpPost]
        public string GetInputParamsText(FormCollection data)
        {
            var itemsCnt = data.Count / 2;
            var assignments = Enumerable.Repeat(0, itemsCnt).Select(i => new CodeTagAssignment()).ToArray();
            for (int i = 0; i < itemsCnt; i++)
            {
                assignments[i].TagGuid = Guid.Parse(data[string.Format("Coll[{0}][TagGuid]", i)]);
                assignments[i].VariableName = data[string.Format("Coll[{0}][VariableName]", i)];
            }

            using (var db = new WombatEntities())
            {
                return TagHelper.GetVariableAssignmentString(db, assignments);
            }
        }

        //
        // GET: /Tag/Details/5

        public ActionResult Details(int id)
        {

            using (var db = new WombatEntities())
            {

                var tag = GetTagByIdAndUpdateViewBag(id);
                var parent = TagHelper.GetLinksTo(db, tag.Id, RelationshipType.ParentChild).FirstOrDefault();
                if (parent != null)
                {
                    ViewBag.Parent = string.Format("{0} [{1}]", parent.SourceTagId, parent.SourceTag.Name);
                }
                if (tag.Type == (int) TagType.Normal)
                {
                    var tagDto = new TagDto()
                        {
                            Id = tag.Id,
                            Name = tag.Name,
                            Guid = tag.Guid,
                            Unit = tag.Unit.Name,
                            UnitId = tag.Unit.Id
                        };
                    return View("DetailsNormal", tagDto);
                }
                if (tag.Type == (int) TagType.Code)
                {
                    var tagCodeDto = new TagFactory().CreateCodeTag(tag);
                    ViewBag.ParametersString = TagHelper.GetParametersString(new WombatEntities(), tagCodeDto);
                    return View("DetailsCode", tagCodeDto);
                }
            }
            return View("Error");
        }

        public JsonResult GetTagById(long id)
        {
            var tag = GetTagByIdAndUpdateViewBag(id);
            return Json( 
                new TagDto {Guid = tag.Guid, Name = tag.Name, Id = tag.Id}
                , JsonRequestBehavior.AllowGet);
        }


        private Tag GetTagByIdAndUpdateViewBag(long id)
        {
            using (var db = new WombatEntities())
            {
                return TagByIdAndUpdateViewBag(id, db);
            }
        }

        private Tag TagByIdAndUpdateViewBag(long id, WombatEntities db)
        {
            var tag = db.Tags
                        .Include("Unit")
                        .FirstOrDefault(t => t.Id == id);
            if (tag != null)
            {
                ViewBag.Name = tag.Name;
                ViewBag.Guid = tag.Guid.ToString();
                ViewBag.Unit = tag.Unit.Name;
            }
            return tag;
        }

        //
        // GET: /Tag/Create

        public ActionResult Create(string tagType = null, bool partial = false)
        {
            ViewBag.TagType = tagType ?? "Select One";
            if (partial)
            {
                switch (tagType)
                {
                    case "Normal":
                        return PartialView("CreateNormal");
                    case "Code":
                        return PartialView("CreateCode");
                }
                return PartialView("Error");
            }
            return View();
        }

        //
        // POST: /Tag/CreateCode

        [HttpPost]
        public ActionResult CreateCode(CodeTagDto codeTagDto)
        {
            try
            {
                var js = new JavaScriptSerializer();
                var parameters = js.Deserialize<CodeTagAssignment[]>(Request.Form["InputParameters"]);
                codeTagDto.InputParameters = parameters;
                using (var db = new WombatEntities())
                {
                    var tagData = new TagFactory().CreateTag(codeTagDto);
                    var tag = new Tag
                    {
                        Name = tagData.Name,
                        Guid = Guid.NewGuid(),
                        Type = (int)TagType.Code,
                        ParameterSchema = tagData.ParameterSchema,
                        Cluster = DefaultsHelper.GetDefaultCluster(db),
                        Unit = DefaultsHelper.GetUnitOrDefault(db, codeTagDto.Unit)
                    }; db.AddToTags(tag);
                    AddParentRelationship(db, tag);
                    db.SaveChanges();
                }
                return RedirectToAction("Index");
            }
            catch (Exception exception)
            {
                return View("Error", new HandleErrorInfo(exception, "Tag", "CreateCode"));
            }
        }

        private void AddParentRelationship(WombatEntities db, Tag tag)
        {
            var parentId = default(long);
            if (!Int64.TryParse(Request.Form["parentId"], out parentId)) return;
            var parent = db.Tags.First(t => t.Id == parentId);
            TagHelper.CreateLink(db, parent, tag, RelationshipType.ParentChild);
        }

        //
        // POST: /Tag/CreateNormal

        [HttpPost]
        public ActionResult CreateNormal(TagDto tagData)
        {
            try
            {

                using (var db = new WombatEntities())
                {
                    var tag = new Tag
                    {
                        Name = tagData.Name,
                        Guid = Guid.NewGuid(),
                        Type = (int)TagType.Normal,
                        ParameterSchema = string.Empty,
                        Cluster = DefaultsHelper.GetDefaultCluster(db),
                        Unit = DefaultsHelper.GetUnitOrDefault(db, tagData.Unit),
                    }; db.AddToTags(tag);
                    AddParentRelationship(db, tag);
                    db.SaveChanges();
                }
                return RedirectToAction("Index");
            }
            catch(Exception exception)
            {
                return View("Error", new HandleErrorInfo(exception, "Tag", "CreateNormal"));
            }
        }


        //
        // GET: /Tag/Edit/5

        public ActionResult Edit(int id)
        {
            GetTagByIdAndUpdateViewBag(id);
            return View();
        }

        //
        // POST: /Tag/Edit/5

        [HttpPost]
        public ActionResult Edit(int id, FormCollection collection)
        {
            try
            {
                var tag = GetTagByIdAndUpdateViewBag(id);
                tag.Name = collection["Name"];
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        //
        // GET: /Tag/Delete/5

        public ActionResult Delete(int id)
        {
            using (var db = new WombatEntities())
            {
                var tag = db.Tags.FirstOrDefault(t => t.Id == id);
                if (tag != null)
                {
                    var relationships = db.TagRelationships.Where(r => r.SourceTagId == id || r.DestinationTagId == id);
                    foreach (var tagRelationship in relationships)
                    {
                        db.DeleteObject(tagRelationship);
                    }
                    db.DeleteObject(tag);
                    db.SaveChanges();
                }
            }
            return RedirectToAction("Index");
        }
    }
}
